// track_silhouette.cpp : main project file.

#include "stdafx.h"
#include <cv.h>
#include "cvaux.h"
#include <cxcore.h>
#include <highgui.h>
#include <stdio.h>

using namespace System;


int main(int argc, char** argv)
{
    IplImage*       tmp_frame = NULL;
    CvCapture*      cap = NULL;

    cap = cvCaptureFromCAM(0);
    tmp_frame = cvQueryFrame(cap);
    if(!tmp_frame)
    {
        printf("bad video \n");
        exit(0);
    }

	CvFGDStatModelParams params = {CV_BGFG_FGD_LC, CV_BGFG_FGD_N1C, CV_BGFG_FGD_N2C, CV_BGFG_FGD_LCC,
                                CV_BGFG_FGD_N1CC, CV_BGFG_FGD_N2CC, 1, 0, CV_BGFG_FGD_ALPHA_1, CV_BGFG_FGD_ALPHA_2,
                                CV_BGFG_FGD_ALPHA_3, CV_BGFG_FGD_DELTA, CV_BGFG_FGD_T, CV_BGFG_FGD_MINAREA};


	params.minArea = 50;
	params.is_obj_without_holes = 1;
	params.alpha2 = 0.0001f;

    cvNamedWindow("BG", 1);
    cvNamedWindow("FG", 1);

    //create BG model
    CvBGStatModel* bg_model = cvCreateFGDStatModel( tmp_frame, &params);

    
    for( int fr = 1;tmp_frame; tmp_frame = cvQueryFrame(cap), fr++ )
    {
        cvUpdateBGStatModel( tmp_frame, bg_model );
        cvShowImage("BG", bg_model->background);
		
		// Ensure origin is the same with both images (prevents images from being flipped
		bg_model->foreground->origin = bg_model->background->origin;
        cvShowImage("FG", bg_model->foreground);
        char k = cvWaitKey(5);
        if( k == 27 ) break;
    }

    cvReleaseBGStatModel( &bg_model );
    cvReleaseCapture(&cap);

    return 0;
}

int main11(int argc, char** argv)
{
    IplImage*       tmp_frame = NULL;
    CvCapture*      cap = NULL;

    cap = cvCaptureFromCAM(0);
    tmp_frame = cvQueryFrame(cap);
    if(!tmp_frame)
    {
        printf("bad video \n");
        exit(0);
    }

    cvNamedWindow("BG", 1);
    cvNamedWindow("FG", 1);

    //create BG model
    CvBGStatModel* bg_model = cvCreateFGDStatModel( tmp_frame );
    
    for( int fr = 1;tmp_frame; tmp_frame = cvQueryFrame(cap), fr++ )
    {
        double t = (double)cvGetTickCount();
        cvUpdateBGStatModel( tmp_frame, bg_model );
        t = (double)cvGetTickCount() - t;
        printf( "%.1f\n", t/(cvGetTickFrequency()*1000.) );
        cvShowImage("BG", bg_model->background);
        cvShowImage("FG", bg_model->foreground);
        char k = cvWaitKey(5);
        if( k == 27 ) break;
    }


    cvReleaseBGStatModel( &bg_model );
    cvReleaseCapture(&cap);

    return 0;
}


int main2(array<System::String ^> ^args) {
    /* Start capturing */
    CvCapture* capture = 0;
	IplImage *flipped = 0;

    capture = cvCaptureFromCAM(0);

    if( !capture )
    {
        fprintf(stderr,"Could not initialize...\n");
        return -1;
    }

    /* print a welcome message, and the OpenCV version */
    printf ("Demo of the background classification using CvGaussBGModel %s (%d.%d.%d)\n",
	    CV_VERSION,
	    CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);

    /* Capture 1 video frame for initialization */
    IplImage* videoFrame = NULL;
    videoFrame = cvQueryFrame(capture);

    if(!videoFrame)
    {
        printf("Bad frame \n");
        exit(0);
    }

    // Create windows
    cvNamedWindow("BG");
    cvNamedWindow("FG");

    // Select parameters for Gaussian model.
    CvGaussBGStatModelParams* params = new CvGaussBGStatModelParams;						
    params->win_size=2;	
    params->n_gauss=5;
    params->bg_threshold=0.7;
    params->std_threshold=2.5;
    params->minArea=400;
    params->weight_init=0.05;
    params->variance_init=30; 

    // Creat CvBGStatModel
    // cvCreateGaussianBGModel( IplImage* first_frame, CvGaussBGStatModelParams* parameters )
    // or
    // cvCreateGaussianBGModel( IplImage* first_frame )
    CvBGStatModel* bgModel = cvCreateGaussianBGModel(videoFrame ,params);

    int key=-1;
    while(key != 'q')
    {
        // Grab a fram
        videoFrame = cvQueryFrame(capture);
        if( !videoFrame )
            break;
        
        // Update model
        cvUpdateBGStatModel(videoFrame,bgModel);
        
        // Display results
		flipped = cvCloneImage(bgModel->background);
		cvFlip(bgModel->background, flipped);
       	cvShowImage("BG", flipped);

		flipped = cvCloneImage(bgModel->foreground);
		cvFlip(bgModel->foreground, flipped);
       	cvShowImage("FG", flipped);	
       	key = cvWaitKey(10);
    }

    cvDestroyWindow("BG");
    cvDestroyWindow("FG");
    cvReleaseBGStatModel( &bgModel );
    cvReleaseCapture(&capture);
    return 0;
}

int main17(array<System::String ^> ^args)
{
	IplImage *image = 0;
	IplImage *grayImg = 0;
	IplImage *frame = 0;
	IplImage *background = 0;
	IplImage *temp = 0;
	CvFont font;
	int calCount = 1;

	cvInitFont(&font,CV_FONT_HERSHEY_PLAIN|CV_FONT_ITALIC,1,1,0,1);

	// Setup camera
	CvCapture* capture = 0;   
	capture = cvCaptureFromCAM(0);			// Use any cam available

	// Check if cam is available
	if(!cvGrabFrame(capture)){
		printf("ERROR: Camera not available\n");
		return 0;
	}

	// Do calibration
	cvNamedWindow("HumanTetris");
	for (int i = 0; i < calCount; i++) {
		// Get next frame
		frame=cvQueryFrame(capture);
		
		// Store grayscale version
		grayImg = cvCreateImage(cvSize(frame->width,frame->height), IPL_DEPTH_8U, 1);		
		cvCvtColor(frame,grayImg,CV_BGR2GRAY);
		
		// Pull color version
		image = cvCloneImage(frame);

		// Show color image
		cvPutText(image,"Calibration running" ,cvPoint(10,10),&font,cvScalar(255,0,0));
		cvShowImage("HumanTetris", image );
		cvWaitKey(10);
	}

	// Hack: use last image
	temp = cvCloneImage(grayImg);
	background = cvCloneImage(grayImg);
	//cvEqualizeHist(temp, background);

	// Show silhouette
	char c = 0;
	
	// Run until "q" is pressed
	int thres = 100;

	while(c != 'q') {
		// Get next frame
		frame=cvQueryFrame(capture);

		// Get color image
		image = cvCloneImage(frame);

		// Store grayscale version
		grayImg = cvCreateImage(cvSize(frame->width,frame->height), IPL_DEPTH_8U, 1);		
		cvCvtColor(frame,grayImg,CV_BGR2GRAY);
		//temp = cvCloneImage(grayImg);
		//cvEqualizeHist(temp, grayImg);

		// Compute difference image
		for (int x=0; x < grayImg->width; x++) {
			for (int y=0; y < grayImg->height; y++) {
				// Calculate current position
				int pos = x + y*grayImg->widthStep;
				
				// Check if difference exeeds threshold
				if (abs(grayImg->imageData[pos] - background->imageData[pos]) > thres) {
					// Color corresponding pixels
					
					/*image->imageData[x*image->nChannels + y*image->widthStep + 0] = 255;
					image->imageData[x*image->nChannels + y*image->widthStep + 1] = 255;
					image->imageData[x*image->nChannels + y*image->widthStep + 2] = 255;*/

					grayImg->imageData[pos] = 0;
				}
			}
		}
		
		// Show output
		cvShowImage("HumanTetris", grayImg);

		// Read in key
		c = cvWaitKey(50);

		// Release images
		cvReleaseImage(&image);
		cvReleaseImage(&grayImg);
	}

	// Clean up
	cvReleaseCapture( &capture );
    cvDestroyWindow("HumanTetris");
    return 0;
}
